﻿using System;
using System.Data;
using System.Drawing;
using System.Threading;
using System.Data.SqlClient;

using COUP.Core.Enums;
using COUP.Core.Networking;

namespace COUP.Core.Database
{
    public class MsSqlDatabase : iDatabase
    {
        private const string _connString = "Data Source=JACK-PC\\SQLEXPRESS;Initial Catalog=Conquer;Integrated Security=True;Pooling=False";
        private SqlConnection _sqlConn = new SqlConnection(_connString);

        public void Remove() { }

        public void Submit(SubmitType Type, params object[] Args)
        {
            switch (Type)
            {
                case SubmitType.NewCharacter:
                    NewCharacter(Args); break;
            }
        }

        public object Select(SelectType Type, params object[] Args)
        {
            switch (Type)
            {
                case SelectType.GetPortal:
                    return GetPortalExit(Args);
                default:
                    return null;
            }
        }

        public void Update(UpdateType Type, params object[] Args)
        {
            switch (Type)
            {
                case UpdateType.Agility:
                    UpdateAgility(Args); break;
                case UpdateType.AttributePoints:
                    UpdateAttributePoints(Args); break;
                case UpdateType.Avatar:
                    UpdateAvatar(Args); break;
                case UpdateType.BankGold:
                    UpdateBankGold(Args); break;
                case UpdateType.Class:
                    UpdateClass(Args); break;
                case UpdateType.Experience:
                    UpdateExperience(Args); break;
                case UpdateType.HairColour:
                    UpdateHairColour(Args); break;
                case UpdateType.HairStyle:
                    UpdateHairStyle(Args); break;
                case UpdateType.Health:
                    UpdateHealth(Args); break;
                case UpdateType.InventoryGold:
                    UpdateInventoryGold(Args); break;
                case UpdateType.Level:
                    UpdateLevel(Args); break;
                case UpdateType.Location:
                    UpdateLocation(Args); break;
                case UpdateType.Mana:
                    UpdateMana(Args); break;
                case UpdateType.Map:
                    UpdateMap(Args); break;
                case UpdateType.Model:
                    UpdateModel(Args); break;
                case UpdateType.Name:
                    UpdateName(Args); break;
                case UpdateType.Password:
                    UpdatePassword(Args); break;
                case UpdateType.PkPoints:
                    UpdatePkPoints(Args); break;
                case UpdateType.Spirit:
                    UpdateSpirit(Args); break;
                case UpdateType.Spouse:
                    UpdateSpouse(Args); break;                    
                case UpdateType.Strength:
                    UpdateStrength(Args); break;
                case UpdateType.SubClass:
                    UpdateSubClass(Args); break;
                case UpdateType.Vitality:
                    UpdateVitality(Args); break;
            }
        }

        internal void ExecuteCommand(SqlCommand Com)
        {
            using (SqlConnection _conn = new SqlConnection(_connString))
            {
                _conn.Open(); Com.Connection = _conn; Com.ExecuteNonQuery();
            }
        }

        #region Update Methods

        internal void UpdatePassword(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateAccountPassword");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@AccountID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.VarChar).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateSpouse(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterSpouse");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.VarChar).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateName(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterName");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.VarChar).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateModel(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterModel");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.Int).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateHairColour(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterHairColour");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.TinyInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateHairStyle(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterHairStyle");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.TinyInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateExperience(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterExperience");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.Int).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateAvatar(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterAvatar");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.SmallInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateClass(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterClass");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.TinyInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateSubClass(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterSubClass");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.TinyInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateAgility(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterAgility");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.SmallInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateVitality(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterVitality");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.SmallInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateStrength(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterStrength");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.SmallInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateSpirit(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterSpirit");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.SmallInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateAttributePoints(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterAttribute");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.SmallInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateLevel(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterLevel");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.TinyInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdatePkPoints(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterPkPoints");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.SmallInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateHealth(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterHealth");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.SmallInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateMana(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterMana");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.SmallInt).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateInventoryGold(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterInventoryGold");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.Int).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateBankGold(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterBankGold");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Value", SqlDbType.Int).Value = Args[1];

            ExecuteCommand(Com);
        }

        internal void UpdateLocation(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterLocation");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@X", SqlDbType.SmallInt).Value = Args[1];
            Com.Parameters.Add("@Y", SqlDbType.SmallInt).Value = Args[2];

            ExecuteCommand(Com);
        }

        internal void UpdateMap(params object[] Args)
        {
            SqlCommand Com = new SqlCommand("UpdateCharacterMap");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@CharacterID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Map", SqlDbType.Int).Value = Args[1];

            ExecuteCommand(Com);
        }

        #endregion

        #region Select Methods

        internal object GetPortalExit(params object[] Args)
        {
            Point Cordinates = (Point)Args[1];

            SqlCommand Com = new SqlCommand("GetPortalExit");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@MapID", SqlDbType.Int).Value = Args[0];
            Com.Parameters.Add("@Cord_X", SqlDbType.SmallInt).Value = Cordinates.X;
            Com.Parameters.Add("@Cord_Y", SqlDbType.SmallInt).Value = Cordinates.Y;
            Com.Parameters["@MapID"].Direction = ParameterDirection.InputOutput;
            Com.Parameters["@Cord_X"].Direction = ParameterDirection.InputOutput;
            Com.Parameters["@Cord_Y"].Direction = ParameterDirection.InputOutput;

            ExecuteCommand(Com);

            return new int[3] { Convert.ToInt32(Com.Parameters[0].Value), Convert.ToInt32(Com.Parameters[1].Value), Convert.ToInt32(Com.Parameters[2].Value) };
        }

        #endregion

        #region Submit Methods

        internal void NewCharacter(params object[] Args)
        {        
            NewCharacterPacket newCharacter = Args[0] as NewCharacterPacket;

            SqlCommand Com = new SqlCommand("InsertNewCharacter");
            Com.CommandType = CommandType.StoredProcedure;
            Com.Parameters.Add("@AccountID", SqlDbType.Int).Value = newCharacter.AccountID;
            Com.Parameters.Add("@ServerID", SqlDbType.Int).Value = Args[1];
            Com.Parameters.Add("@Avatar", SqlDbType.SmallInt).Value = newCharacter.Avatar;
            Com.Parameters.Add("@ModelID", SqlDbType.SmallInt).Value = newCharacter.ModelID;
            Com.Parameters.Add("@Class", SqlDbType.SmallInt).Value = newCharacter.Job;
            Com.Parameters.Add("@CharacterName", SqlDbType.VarChar).Value = newCharacter.Name;

            ExecuteCommand(Com);
        }

        #endregion
    }
}
